﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ifunction.LifeVC.CheckInServiceCore;
using Newtonsoft.Json;

namespace ifunction.LifeVC.CheckInService
{
    /// <summary>
    /// Class LifeVCService.
    /// </summary>
    public class LifeVCService : ILifeVCService
    {
        /// <summary>
        /// The account file
        /// </summary>
        protected const string accountFile = "accounts.json";

        /// <summary>
        /// Gets the account file path.
        /// </summary>
        /// <value>The account file path.</value>
        protected static string AccountFilePath
        {
            get
            {
                return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, accountFile);
            }
        }

        /// <summary>
        /// The locker
        /// </summary>
        protected static object locker = new object();

        /// <summary>
        /// The session
        /// </summary>
        protected static List<LifeVCSession> session = null;

        /// <summary>
        /// The monitor thread
        /// </summary>
        protected static Thread monitorThread = null;

        /// <summary>
        /// Trigs the monitor.
        /// </summary>
        public static void TrigMonitor()
        {
            Initialized();
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is debug.
        /// </summary>
        /// <value><c>true</c> if this instance is debug; otherwise, <c>false</c>.</value>
        public bool IsDebug { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="LifeVCService" /> class.
        /// </summary>
        public LifeVCService()
        {
            this.IsDebug = true;

            if (session == null)
            {
                lock (locker)
                {
                    if (session == null)
                    {
                        session = new List<LifeVCSession>();

                        ReadAccounts(this.IsDebug);
                        InitializeThread();
                    }
                }
            }
        }

        protected static void Initialized()
        {
            if (session == null)
            {
                lock (locker)
                {
                    if (session == null)
                    {
                        session = new List<LifeVCSession>();

                        ReadAccounts();
                        InitializeThread();
                    }
                }
            }
        }

        /// <summary>
        /// Initializes the thread.
        /// </summary>
        protected static void InitializeThread()
        {
            monitorThread = new Thread(new ThreadStart(MonitorDelegate));
            monitorThread.IsBackground = true;
            Framework.Logger.LogMessageWithTimeStamp("Monitor Thread Initialized.");
            monitorThread.Start();
        }

        /// <summary>
        /// Monitors the delegate.
        /// </summary>
        protected static void MonitorDelegate()
        {
            while (true)
            {
                lock (locker)
                {
                    foreach (var one in session)
                    {
                        try
                        {
                            if (one.HasLogin)
                            {
                                string outMessage;
                                one.CheckIn(out outMessage);

                                one.CheckSignIn();
                            }
                            else
                            {
                                one.Login();
                            }
                        }
                        catch { }
                    }
                }

                Thread.Sleep(30000);
            }
        }

        /// <summary>
        /// Reads the accounts.
        /// </summary>
        protected static void ReadAccounts(bool isDebug = true)
        {
            try
            {
                string accountContent = File.ReadAllText(AccountFilePath, Encoding.UTF8);
                var list = JsonConvert.DeserializeObject<List<LifeVCAccount>>(accountContent);

                foreach (var one in list)
                {
                    session.Add(new LifeVCSession(one, isDebug));

                    if (isDebug)
                    {
                        Framework.Logger.LogMessageWithTimeStamp("Account added: " + one.Email);
                    }
                }
            }
            catch (Exception ex)
            {
                Framework.Logger.LogException(ex);
            }
        }


        /// <summary>
        /// Writes the accounts.
        /// </summary>
        protected void WriteAccounts()
        {
            List<LifeVCAccount> accounts = new List<LifeVCAccount>();

            foreach (var one in session)
            {
                accounts.Add(one);
            }

            string json = JsonConvert.SerializeObject(accounts);
            File.WriteAllText(AccountFilePath, json, Encoding.UTF8);
        }

        /// <summary>
        /// Gets the account.
        /// </summary>
        /// <param name="identity">The identity.</param>
        /// <returns>LifeVCAccount.</returns>
        public LifeVCAccount GetAccount(string identity)
        {
            if (!string.IsNullOrWhiteSpace(identity))
            {
                lock (locker)
                {
                    for (var i = 0; i < session.Count; i++)
                    {
                        if (session[i].CellPhone == identity || session[i].Email == identity)
                        {
                            return session[i] as LifeVCAccount;
                        }
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// Adds the account.
        /// </summary>
        /// <param name="account">The account.</param>
        /// <exception cref="System.Exception">Already exists account: + account.Email</exception>
        public void AddAccount(LifeVCAccount account)
        {
            if (account != null)
            {
                if (GetAccount(account.Email) != null)
                {
                    throw new Exception("Already exists account:" + account.Email);
                }
                else
                {
                    lock (locker)
                    {
                        session.Add(new LifeVCSession(account, IsDebug));
                        WriteAccounts();
                    }
                }
            }
        }

        /// <summary>
        /// Removes the account.
        /// </summary>
        /// <param name="identity">The identity.</param>
        public void RemoveAccount(string identity)
        {
            if (!string.IsNullOrWhiteSpace(identity))
            {
                lock (locker)
                {
                    for (var i = 0; i < session.Count; i++)
                    {
                        if (session[i].CellPhone == identity || session[i].Email == identity)
                        {
                            session.RemoveAt(i);
                            WriteAccounts();
                            break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Finds the account.
        /// </summary>
        /// <param name="identity">The identity.</param>
        /// <returns>List{LifeVCAccount}.</returns>
        public List<LifeVCAccount> FindAccount(string identity = null)
        {
            List<LifeVCAccount> result = new List<LifeVCAccount>();

            lock (locker)
            {
                for (var i = 0; i < session.Count; i++)
                {
                    if (string.IsNullOrWhiteSpace(identity) || session[i].CellPhone == identity || session[i].Email == identity)
                    {
                        result.Add(
                            new LifeVCAccount
                            {
                                CellPhone = session[i].CellPhone,
                                Email = session[i].Email,
                                HasLogin = session[i].HasLogin,
                                Points = session[i].Points,
                                LastCheckInStamp = session[i].LastCheckInStamp
                            });
                    }
                }
            }

            return result;
        }
    }
}
